package org.example.auth.service.authStrategy;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import org.example.auth.domain.LoginUserDetails;
import org.example.auth.domain.SocialLoginBody;
import org.example.auth.service.IAuthStrategy;
import org.example.auth.service.IAuthUserStrategy;
import org.example.auth.service.SysLoginService;
import org.example.common.core.constants.Constants;
import org.example.common.core.domain.model.LoginModel;
import org.example.common.core.domain.model.LoginSocial;
import org.example.common.core.domain.model.LoginSocialConfig;
import org.example.common.core.domain.model.LoginUser;
import org.example.common.core.exception.ServiceException;
import org.example.common.core.utils.MessageUtils;
import org.example.common.core.utils.StringUtils;
import org.example.common.core.utils.ValidatorUtils;
import org.example.common.redis.utils.LoginHelper;
import org.example.common.social.config.properties.SocialLoginConfigProperties;
import org.example.common.social.config.properties.SocialProperties;
import org.example.common.social.utils.SocialUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 第三方登录
 */
@Slf4j
@Service("social"+IAuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class SocialAuthStrategy implements IAuthStrategy {

    private final SysLoginService sysLoginService;

    @Override
    public UserDetails authentication(UsernamePasswordAuthenticationToken authenticationToken) {
        Object object= authenticationToken.getDetails();
        SocialLoginBody loginBody=JSON.parseObject(JSON.toJSONString(object),SocialLoginBody.class);
        ValidatorUtils.validate(loginBody);
        sysLoginService.checkTenant(loginBody.getTenant_id());
        Map<String, SocialLoginConfigProperties> type=new HashMap<>();
        Map<String, LoginSocialConfig> map= IAuthUserStrategy.getLoginSocialConfig(loginBody.getGrant_user().getCode(),loginBody.getTenant_id());
        if(map.size()==0){
            throw new ServiceException("不支持第三方账号登录");
        }
        SocialProperties socialProperties=new SocialProperties();
        map.forEach((k, v)->{
            SocialLoginConfigProperties properties=new SocialLoginConfigProperties();
            BeanUtils.copyProperties(v,properties);
            type.put(k,properties);
        });
        socialProperties.setEnabled(true);
        socialProperties.setType(type);
        AuthResponse<AuthUser> response = SocialUtils.loginAuth(
                loginBody.getSource(), loginBody.getSocialCode(),
                loginBody.getSocialState(), socialProperties);
        if (!response.ok()) {
            log.error("【第三方账号登录】》》授权登录失败，租户：{} code：{}",loginBody.getTenant_id(),loginBody.getSocialCode());
            throw new ServiceException(response.getMsg());
        }
        AuthUser authUserData = response.getData();
        String authId = authUserData.getSource() + authUserData.getUuid();

        LoginSocial socialVo = IAuthUserStrategy.getLoginSocialByAuthId(loginBody.getGrant_user().getCode(),loginBody.getTenant_id(),authId);
        if (ObjectUtil.isEmpty(socialVo)) {
            log.error("【第三方账号登录】》》授权登录失败，租户：{} code：{}",loginBody.getTenant_id(),loginBody.getSocialCode());
            throw new ServiceException("授权登录失败");
        }
        LoginUser loginUser = IAuthUserStrategy.getLoginUserByUserId(loginBody.getGrant_user().getCode(),
                socialVo.getTenantId(),socialVo.getUserId());

        LoginModel loginModel=LoginModel.create();
        loginModel.setTimeout(loginBody.getExpires_in());
        loginModel.setToken(StringUtils.getUUID());
        loginModel.setDevice(loginBody.getDevice_type());
        loginModel.setGrantUser(loginBody.getGrant_user().getCode());

        LoginHelper.login(loginUser,loginModel);

        sysLoginService.recordLogininfor(loginUser.getTenantId(),loginUser.getUsername(),loginModel.getDevice(),Constants.SUCCESS,MessageUtils.message("user.login.success"));

        LoginUserDetails loginUserDetails= new LoginUserDetails(loginUser.getUsername(),
                loginUser.getPassword(),
                AuthorityUtils.createAuthorityList());
        loginUserDetails.setGrantUser(loginModel.getGrantUser());
        loginUserDetails.setDeviceType(loginModel.getDevice());
        loginUserDetails.setToken(loginModel.getToken());
        loginUserDetails.setTenantId(loginBody.getTenant_id());
        return loginUserDetails;
    }
}
